うっかりrdsproxyadminのパスワードを変更してもRDS Proxyが正常動作するのか確認してみた
MAD事業部@大阪の岩田です。
RDS Proxyを作成するとRDS側にrdsproxyadmin
というDBユーザーが作成されます。RDS Proxyを構築したRDSに対してクエリを発行すると、このrdsoroxyadmin
ユーザーがバックエンドで何をしているのかが想像できます。例えば、以下はRDS for PostgreSQLに対してクエリを実行した結果です。
postgres=> select * from pg_stat_activity where usename = 'rdsproxyadmin'; -[ RECORD 1 ]----+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- datid | 14301 datname | postgres pid | 31648 leader_pid | usesysid | 16418 usename | rdsproxyadmin application_name | client_addr | 172.31.25.179 client_hostname | client_port | 60973 backend_start | 2022-05-21 08:49:00.251829+00 xact_start | query_start | 2022-05-21 08:58:12.352717+00 state_change | 2022-05-21 08:58:12.352914+00 wait_event_type | Client wait_event | ClientRead state | idle backend_xid | backend_xmin | query | SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime; backend_type | client backend -[ RECORD 2 ]----+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- datid | 14301 datname | postgres pid | 31668 leader_pid | usesysid | 16418 usename | rdsproxyadmin application_name | client_addr | 172.31.14.233 client_hostname | client_port | 51371 backend_start | 2022-05-21 08:49:00.604766+00 xact_start | query_start | 2022-05-21 08:58:12.472398+00 state_change | 2022-05-21 08:58:12.472623+00 wait_event_type | Client wait_event | ClientRead state | idle backend_xid | backend_xmin | query | SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime; backend_type | client backend
max_connections
のような設定値を取得しているのが分かります。これはRDS Proxyのターゲットグループに設定値できる「接続プールの最大接続数」の割合に応じて、コネクションプールで管理するDB接続数を計算するためだと推測できます。
ここで1つ疑問が生まれます。rdsoroxyadmin
ユーザーがRDSに接続できなくなり、max_connections
のような設定値が取得できなくなるとRDS Proxyはどうなるのでしょうか?正常に利用できなくなってしまうのでしょうか?ということでrdsoroxyadmin
ユーザーのパスワードを変更するとどうなるか試してみました。
環境
今回利用したRDSの環境です
- RDS for PostgreSQL
- エンジンバージョン 13.6
- インスタンスクラス db.t3.micro
やってみる
軽く事前準備と確認
まずはRDS & RDS Proxyの環境を構築します。手順の詳細は割愛しますが、今回はuser01というDBユーザーを作成し、このDBユーザー用のシークレットをRDS Proxyに設定しました。また、user01が接続可能なdb1というデータベースも作成しています。
適当なEC2からpsqlでRDS Proxy経由でRDSに接続してクエリを発行してみます
[ec2-user@ip-172-31-9-117 ~]$ psql -h <RDSプロキシのエンドポイント> -U user01 db1 Password for user user01: psql (13.3, server 13.6) SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off) Type "help" for help. db1=> select now(); now ------------------------------- 2022-05-21 09:18:55.341477+00 (1 row)
OKです。
これでRDS Proxyのコネクションプールにuser01用のDB接続がプーリングされたので、別のpsqlセッションからRDSに直接接続し、RDS <-> RDS Proxy間の接続をクローズしておきます。
postgres=> select pid from pg_stat_activity where usename = 'user01'; pid ------- 30349 2604 (2 rows) postgres=> select pg_terminate_backend(2604); pg_terminate_backend ---------------------- t (1 row) postgres=> select pg_terminate_backend(30349); pg_terminate_backend ---------------------- t (1 row) postgres=> select pid from pg_stat_activity where usename = 'user01'; pid ----- (0 rows)
rdsproxyadminのパスワードを変更してみる
ここからが本題です。RDSのマスターユーザーを使ってrdsproxyadmin
のパスワードを変更してみましょう。psqlからRDSに直接接続し、以下のSQLを発行します。
postgres=> alter role rdsproxyadmin with password 'hogehogehogehoge'; ALTER ROLE
特にエラーなくパスワードが変更できてしまいました。続いてすでに確立済みのRDS Proxy <-> RDS間の接続を全てクローズします。これで、以後RDS Proxyはrdsproxyadmin
ユーザーを使ってRDSに接続できなくなり、max_connections
のような情報が取得できなくなるはずです。
postgres=> select pid from pg_stat_activity where usename = 'rdsproxyadmin'; pid ------- 12636 12640 (2 rows) postgres=> select pg_terminate_backend(12636); pg_terminate_backend ---------------------- t (1 row) postgres=> select pg_terminate_backend(12640); pg_terminate_backend ---------------------- t (1 row)
準備が整ったので、EC2からRDS Proxyに接続します
psql -h <RDSプロキシのエンドポイント> -U user01 db1 Password for user user01: psql (13.3, server 13.6) SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off) Type "help" for help.
接続に成功しました。この時点ではあくまでpsql <-> RDS Proxy間の接続に成功しただけで、RDS <-> RDS Proxy間の接続は確立していません。
実際にクエリを発行してみます。本来であればこれでRDS <-> RDS Proxy間の接続が確立し、RDS Proxy経由でRDSにクエリが発行されるはずです。
db1=> select now();
一瞬で実行完了しそうなクエリですが、なかなか応答が返ってきません。やはりrdsproxyadmin
のパスワードを変更したことでRDS PRoxyが壊れてしまったのでしょうか??と思いきや、、、
db1=> select now(); now ------------------------------ 2022-05-21 09:28:29.46803+00 (1 row)
20秒ほど待った時点で応答が返ってきました!この約20秒の間にRDS Proxyが管理しているrdsproxyadmin
ユーザーのパスワードが再設定されたということでしょうか?
ログを分析してみる
こんなこともあろうかとlog_statement=allの設定を入れていたので、裏側で何が起こっていたのかログを見ながら分析してみましょう。ノイズになりそうな部分は省略して主要なログだけ抜粋しています。
まずはrdsproxyadmin
ユーザーのパスワードを変更したログです
2022-05-21 09:23:41 UTC:172.31.9.117(42870):postgres@postgres:[2245]:LOG: statement: alter role rdsproxyadmin with password 'hogehogehogehoge';
すでに確立済のDBセッションはパスワード変更の影響を受けないので、引き続きrdsproxyadmin
ユーザーからクエリが発行されています。
2022-05-21 09:23:41 UTC:172.31.25.179(42465):rdsproxyadmin@postgres:[12636]:LOG: statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime; 2022-05-21 09:23:41 UTC:172.31.14.233(26535):rdsproxyadmin@postgres:[12640]:LOG: statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime; 2022-05-21 09:23:42 UTC:172.31.25.179(42465):rdsproxyadmin@postgres:[12636]:LOG: statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;
確立済のDBセッションをクローズしたログです
2022-05-21 09:27:27 UTC:172.31.9.117(42870):postgres@postgres:[2245]:LOG: statement: select pg_terminate_backend(12636); 2022-05-21 09:27:27 UTC:172.31.25.179(42465):rdsproxyadmin@postgres:[12636]:FATAL: terminating connection due to administrator command
多少順番が前後してしまいますがpid12640の方もクローズしています
2022-05-21 09:27:29 UTC:172.31.9.117(42870):postgres@postgres:[2245]:LOG: statement: select pg_terminate_backend(12640); 2022-05-21 09:27:29 UTC:172.31.14.233(26535):rdsproxyadmin@postgres:[12640]:FATAL: terminating connection due to administrator command
その後新たにrdsproxyadmin用のセッションを確立すべくRDS ProxyからRDSに接続を試行しているログが確認できます。パスワードはRDS Proxyが認識していないhogehogehogehoge
に変更されているので、接続に失敗していることが分かります。
2022-05-21 09:27:28 UTC:172.31.25.179(24407):rdsproxyadmin@postgres:[12780]:FATAL: password authentication failed for user "rdsproxyadmin" 2022-05-21 09:27:28 UTC:172.31.25.179(24407):rdsproxyadmin@postgres:[12780]:DETAIL: Password does not match for user "rdsproxyadmin". Connection matched pg_hba.conf line 13: "host all all all md5" 2022-05-21 09:27:29 UTC:172.31.25.179(4727):rdsproxyadmin@postgres:[12804]:FATAL: password authentication failed for user "rdsproxyadmin" 2022-05-21 09:27:29 UTC:172.31.25.179(4727):rdsproxyadmin@postgres:[12804]:DETAIL: Password does not match for user "rdsproxyadmin". Connection matched pg_hba.conf line 13: "host all all all md5" 2022-05-21 09:27:30 UTC:172.31.14.233(48579):rdsproxyadmin@postgres:[12860]:FATAL: password authentication failed for user "rdsproxyadmin" 2022-05-21 09:27:30 UTC:172.31.14.233(48579):rdsproxyadmin@postgres:[12860]:DETAIL: Password does not match for user "rdsproxyadmin". Connection matched pg_hba.conf line 13: "host all all all md5"
psqlからselect now()
を実行したあたりのログです。接続失敗のログが止まり、max_connections
等の設定値を取得するクエリのログが確認できます。その後select now()
に成功したログが確認できます。
2022-05-21 09:28:28 UTC:172.31.25.179(61119):rdsproxyadmin@postgres:[13979]:FATAL: password authentication failed for user "rdsproxyadmin" 2022-05-21 09:28:28 UTC:172.31.25.179(61119):rdsproxyadmin@postgres:[13979]:DETAIL: Password does not match for user "rdsproxyadmin". Connection matched pg_hba.conf line 13: "host all all all md5" 2022-05-21 09:28:28 UTC:172.31.14.233(22933):rdsproxyadmin@postgres:[13991]:LOG: statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime; 2022-05-21 09:28:29 UTC:172.31.25.179(31605):rdsproxyadmin@postgres:[14006]:LOG: statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime; 2022-05-21 09:28:29 UTC:172.31.25.179(14657):user01@db1:[14007]:LOG: statement: select now(); 2022-05-21 09:28:29 UTC:172.31.14.233(22933):rdsproxyadmin@postgres:[13991]:LOG: statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;
rdsproxyadmin
ユーザーのパスワードを変更する(元に戻す?)ログこそ確認できませんでしたが、上記のログから考えるとユーザー側で無理矢理rdsproxyadmin
ユーザーのパスワードを変更しても、RDS Proxyの基盤側でrdsproxyadmin
のパスワードを再設定するため、最小限のダウンタイムで復旧できると考えて良さそうです。
まとめ
まあ普通はやらないと思いますが、うっかりrdsproxyadmin
ユーザーのパスワードを変更しても安心です!